package com.bestcem.xm.member.grpc.service;

import com.bestcem.xm.common.core.domain.web.RpcStatusResult;
import com.bestcem.xm.common.core.domain.web.ServiceResult;
import com.bestcem.xm.common.core.uitls.EnumUtil;
import com.bestcem.xm.common.core.uitls.GRpcUtil;
import com.bestcem.xm.member.enums.DisplayRangeTypeEnum;
import com.bestcem.xm.member.enums.MemberTypeEnum;
import com.bestcem.xm.member.grpc.service.param.displayrange.CreateDisplayRangeParam;
import com.bestcem.xm.member.grpc.service.param.displayrange.GetDisplayRangeParam;
import com.bestcem.xm.member.grpc.service.param.displayrange.UpdateDisplayRangeParam;
import com.bestcem.xm.member.grpc.v1.common.*;
import com.bestcem.xm.member.service.DisplayRangeService;
import com.bestcem.xm.member.service.dto.DisplayRangeDto;
import io.grpc.stub.StreamObserver;
import lombok.extern.slf4j.Slf4j;
import net.devh.boot.grpc.server.service.GrpcService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;

import javax.validation.ConstraintViolation;
import java.util.ArrayList;
import java.util.Optional;
import java.util.Set;

/**
 * @author dc.wang <dc.wang@idiaoyan.com>
 * @version V1.0
 * @description 联系人展示方式
 * @date 2021/7/19
 */
@Slf4j
@GrpcService
public class DisplayRangeGrpcService extends DisplayRangeServiceGrpc.DisplayRangeServiceImplBase {

    private final DisplayRangeService displayRangeService;

    @Autowired
    public DisplayRangeGrpcService(DisplayRangeService displayRangeService){
        this.displayRangeService = displayRangeService;
    }

    @Override
    public void getDisplayRange(GetDisplayRangeRequest request, StreamObserver<GetDisplayRangeResponse> responseObserver) {
        GetDisplayRangeResponse.Builder builder = GetDisplayRangeResponse.newBuilder();

        MemberTypeEnum memberTypeEnum = EnumUtil.getEnumByIndex(MemberTypeEnum.class, request.getMemberTypeValue());

        // 参数校验
        GetDisplayRangeParam getParam = new GetDisplayRangeParam(request.getOrgId(), memberTypeEnum);
        Set<ConstraintViolation<Object>> violations = GRpcUtil.validateParam(getParam);
        if (!CollectionUtils.isEmpty(violations)) {
            ConstraintViolation<Object> violation = violations.iterator().next();
            builder.setStatus(RpcStatusResult.error(violation.getMessage()));
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
            return;
        }

        ServiceResult<DisplayRangeDto> result = displayRangeService.getDisplayRange(getParam);
        if(!result.isSuccess()){
            builder.setStatus(RpcStatusResult.error(result.getMsg()));
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
            return;
        }
        builder.setStatus(RpcStatusResult.success());
        builder.setDisplayRange(this.getDisplayRangeBuilder(result.getData()));
        responseObserver.onNext(builder.build());
        responseObserver.onCompleted();
    }

    // DisplayRange.Builder 转化方法
    private DisplayRange.Builder getDisplayRangeBuilder(DisplayRangeDto displayRangeDto){
        DisplayRange.Builder builder = DisplayRange.newBuilder();
        com.bestcem.xm.member.grpc.v1.enums.DisplayRangeTypeEnum.DisplayRangeType displayRangeType =
                com.bestcem.xm.member.grpc.v1.enums.DisplayRangeTypeEnum.DisplayRangeType.forNumber(displayRangeDto.getType());

        builder.setType(displayRangeType);
        builder.addAllRoleIds(Optional.ofNullable(displayRangeDto.getRoleIds()).orElse(new ArrayList<>(0)));
        return builder;
    }

    @Override
    public void createDisplayRange(CreateDisplayRangeRequest request, StreamObserver<CreateResponse> responseObserver) {
        CreateResponse.Builder builder = CreateResponse.newBuilder();

        DisplayRange displayRange = request.getDisplayRange();
        MemberTypeEnum memberTypeEnum = EnumUtil.getEnumByIndex(MemberTypeEnum.class, displayRange.getMemberTypeValue());
        DisplayRangeTypeEnum displayRangeTypeEnum = DisplayRangeTypeEnum.getByIndex(displayRange.getTypeValue());

        CreateDisplayRangeParam createParam = new CreateDisplayRangeParam(displayRange.getOrgId(), memberTypeEnum, displayRangeTypeEnum);

        // 参数校验
        Set<ConstraintViolation<Object>> violations = GRpcUtil.validateParam(createParam);
        if (!CollectionUtils.isEmpty(violations)) {
            ConstraintViolation<Object> violation = violations.iterator().next();
            builder.setStatus(RpcStatusResult.error(violation.getMessage()));
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
            return;
        }

        ServiceResult<DisplayRangeDto> result = displayRangeService.createDisplayRange(createParam);
        if(!result.isSuccess()){
            builder.setStatus(RpcStatusResult.error(result.getMsg()));
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
            return;
        }
        builder.setStatus(RpcStatusResult.success());
        builder.setId(result.getData().getId());
        responseObserver.onNext(builder.build());
        responseObserver.onCompleted();
    }

    @Override
    public void updateDisplayRange(UpdateDisplayRangeRequest request, StreamObserver<UpdateResponse> responseObserver) {
        UpdateResponse.Builder builder = UpdateResponse.newBuilder();

        DisplayRange displayRange = request.getDisplayRange();
        MemberTypeEnum memberTypeEnum = EnumUtil.getEnumByIndex(MemberTypeEnum.class, displayRange.getMemberTypeValue());
        DisplayRangeTypeEnum displayRangeTypeEnum = DisplayRangeTypeEnum.getByIndex(displayRange.getTypeValue());

        UpdateDisplayRangeParam param = new UpdateDisplayRangeParam(displayRange.getOrgId(), memberTypeEnum, displayRangeTypeEnum);


        // 参数校验
        Set<ConstraintViolation<Object>> violations = GRpcUtil.validateParam(param);
        if (!CollectionUtils.isEmpty(violations)) {
            ConstraintViolation<Object> violation = violations.iterator().next();
            builder.setStatus(RpcStatusResult.error(violation.getMessage()));
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
            return;
        }

        ServiceResult<DisplayRangeDto> result = displayRangeService.updateDisplayRange(param);
        if(!result.isSuccess()){
            builder.setStatus(RpcStatusResult.error(result.getMsg()));
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
            return;
        }
        builder.setStatus(RpcStatusResult.success());
        builder.setId(result.getData().getId());
        responseObserver.onNext(builder.build());
        responseObserver.onCompleted();
    }
}
